﻿#region codejockey.net Copyright Banner
/****************************************************************\
 * Copyright 2010-2012 codejockey.net.                          *
\****************************************************************/
#endregion

#region Using Directives

using System;
using System.Collections.Generic;

using codejockey.Shared.Text.ReplacementTokens;
using codejockey.BingPaper.Utils;

using log4net;
using log4net.Config;

#endregion

namespace codejockey.BingPaper.TokenConsole
{
	public enum CommandResult
	{
		TokenProcessed,
		UnknownCommandProvided,
		ExitRequested,
		HelpRequested,
		LoadRequested,
		ClearRequested,
		ListVerboseRequested,
		ListSmallRequested,
		ClsRequested
	}

	public static class Program
	{
		private static int _operations;
		private static ILog log;

		static void Main(string[] args)
		{
			if (args == null) 
				throw new ArgumentNullException("args");
			
			XmlConfigurator.Configure();
			//static log4net.ILog Log = log4net.LogManager.GetLogger(            System.Reflection.MethodBase.GetCurrentMethod().DeclaringType        );
			log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

			if (log.IsInfoEnabled)
				log.Info("BingPaper Token Console Started.");

			Console.ForegroundColor = ConsoleColor.White;
			GenerateBanner();

			ProcessCommand();
		}

		private static void ProcessCommand()
		{
			bool endLoop = false;

			if (log.IsDebugEnabled)
				log.Debug("Entered ProcessCommand.");

			do
			{
				GeneratePrompt();
				var command = Console.ReadLine();

				if (log.IsDebugEnabled)
					log.DebugFormat("Command: [{0}]", command);

				var processResult = ProcessUserInput(command);
				_operations++;

				if (log.IsDebugEnabled)
					log.DebugFormat("Operation incremented: [{0}]", _operations);

				switch (processResult)
				{
					case CommandResult.ExitRequested:
						{
							endLoop = true;
							break;
						}

					case CommandResult.ClsRequested:
						{
							Console.Clear();
							break;
						}

					case CommandResult.HelpRequested:
						{
							GenerateHelp();
							break;
						}

					case CommandResult.ClearRequested:
						{
							ClearTokens();
							break;
						}

					case CommandResult.LoadRequested:
						{
							LoadTokens();
							break;
						}

					case CommandResult.ListVerboseRequested:
						{
							GenerateVerboseTokenList();
							break;
						}

					case CommandResult.ListSmallRequested:
						{
							GenerateTokenList();
							break;
						}

					case CommandResult.UnknownCommandProvided:
						{
							Console.WriteLine(string.Format("Unknown command: {0}.", command));
							break;
						}

					default:
						{
							Console.WriteLine("Done.");
							break;
						}
				}
			}
			while (!endLoop);
			Console.WriteLine("Goodbye!");
		}

		private static void ClearTokens()
		{
			Console.WriteLine("Unloading tokens.");
			TokenManager.Tokens.Clear();
			Console.WriteLine("Done.  The token manager is now empty.");
		}

		private static void LoadTokens()
		{
			switch (TokenManager.Tokens.Count)
			{
				case 0:
					Console.WriteLine("Loading tokens, please wait...");
					BingUtils.LoadTokens();

					if (log.IsDebugEnabled)
					{
						log.DebugFormat("Done.  [{0}] tokens loaded.", TokenManager.Tokens.Count);
						log.Debug("Tokens are now available as commands.");

					}

					Console.WriteLine(string.Format("Done.  {0} tokens loaded.", TokenManager.Tokens.Count));
					Console.WriteLine("Tokens are now available as commands.");
					Console.WriteLine("Enter a token to see it's return value.  Use ? for help.");
					break;
			}
		}

		private static void GenerateVerboseTokenList()
		{
			LoadTokens();

			foreach (KeyValuePair<string, IReplacementToken> curToken in TokenManager.Tokens)
			{
				Console.WriteLine(string.Format("--=[{0}]=--------", curToken.Value.Name));
				Console.WriteLine(string.Format("Token: {0}", curToken.Key));
				Console.WriteLine(string.Format("{0}", curToken.Value.Description));
				Console.WriteLine(string.Format("{0}", curToken.Value.ReplaceValue));
				Console.WriteLine("");
			}
			Console.WriteLine("Done.");
		}

		private static void GenerateTokenList()
		{
			if (log.IsInfoEnabled)
				log.Info("GenerateTokenList called.");

			LoadTokens();

			foreach (var curToken in TokenManager.Tokens)
			{
				Console.WriteLine(curToken.Key);

				if (log.IsDebugEnabled)
					log.DebugFormat("Token: [{0}]  Replacement Value: [{1}]", curToken.Key, curToken.Value.ReplaceValue);

			}

			if (log.IsInfoEnabled)
				log.Info("Token list generation complete.");
		}

		private static void GenerateHelp()
		{
			Console.WriteLine("Commands: ");
			Console.WriteLine("  ?/Help - Displays this page.");
			Console.WriteLine("  Load - Loads the tokens for the token manager utilitize during processing.");
			Console.WriteLine("  List - Lists just the tokens that are loaded.");
			Console.WriteLine("  ListVerbose - Lists the tokens the token manager current has loaded with detailed information.");
			Console.WriteLine("  Clear - Clears the token list and unloads all loaded tokens from the manager.");
		}

		#region Commands

		private const string QuitCommandText = "Quit";
		private const string ExitCommandText = "Exit";
		private const string HelpCommandText = "?";
		private const string HelpCommandVerboseText = "Help";
		private const string VerboseListCommandText = "ListVerbose";
		private const string ListCommandText = "List";
		private const string LoadCommandText = "Load";
		private const string ClearCommandText = "Clear";
		private const string ClsCommandText = "Cls";

		#endregion

		private static CommandResult ProcessUserInput(string command)
		{
			if (log.IsInfoEnabled)
				log.Info("ProcessUserInputCalled.");

			var result = CommandResult.UnknownCommandProvided;

			if (log.IsDebugEnabled)
				log.DebugFormat("Provided Command: [{0}]", command);

			if (command.Equals(QuitCommandText, StringComparison.OrdinalIgnoreCase) || command.Equals(ExitCommandText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.ExitRequested;

			if (command.Equals(ClsCommandText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.ClsRequested;

			if (command.Equals(HelpCommandText, StringComparison.OrdinalIgnoreCase) || command.Equals(HelpCommandVerboseText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.HelpRequested;

			if (command.Equals(VerboseListCommandText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.ListVerboseRequested;

			if (command.Equals(ListCommandText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.ListSmallRequested;

			if (command.Equals(ClearCommandText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.ClearRequested;

			if (command.Equals(LoadCommandText, StringComparison.OrdinalIgnoreCase))
				result = CommandResult.LoadRequested;

			if (result == CommandResult.UnknownCommandProvided && TokenManager.Tokens.Count > 0)
			{
				string parseResult = TokenManager.Parse(command);

				if (!string.IsNullOrEmpty(parseResult) && !parseResult.Equals(command))
				{
					if (log.IsDebugEnabled)
						log.DebugFormat("Token detected.  Token value: [{0}] token replacement value: [{1}]", command, parseResult);

					Console.WriteLine(parseResult);
					result = CommandResult.TokenProcessed;
				}
			}

			if (log.IsDebugEnabled)
				log.DebugFormat("Result of command: [{0}]", result.ToString());

			return result;
		}

		private static void GeneratePrompt()
		{
			if (log.IsInfoEnabled)
				log.Info("Generating user prompt...");


			var startingColor = Console.ForegroundColor;

			Console.ForegroundColor = ConsoleColor.Green;
			Console.Write("[");
			Console.ForegroundColor = ConsoleColor.Yellow;
			Console.Write(string.Format("{0} @ {1} (T:{2} O:{3})", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), TokenManager.Tokens.Count, _operations));
			Console.ForegroundColor = ConsoleColor.Green;
			Console.Write("]");
			Console.Write("=>");
			Console.ForegroundColor = startingColor;
		}

		private static void GenerateBanner()
		{
			if (log.IsInfoEnabled)
				log.Info("Generating banner...");
			
			Console.WriteLine("TokenConsole - By: Eric Brown.  Copyright 2010, codejockey.net");

			if (log.IsDebugEnabled)
				log.DebugFormat("Tokens loaded: [{0}]", TokenManager.Tokens.Count);

			if (TokenManager.Tokens.Count > 0)
			{
				if (log.IsDebugEnabled)
					log.Debug("There are tokens present, token tigger values are available as commands.");
			}
		}
	}
}
